home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 365_02 / ref.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  12KB  |  522 lines

  1. /* ref2.c */
  2.  
  3. /* This is a totally rewritten version of ref.  This version looks for the
  4.  * desired function name in the "tags" file, and then reads the header out
  5.  * from the source file.  There is no longer any need for a "refs" file.
  6.  *
  7.  * Usage:    ref [-a] [-t] [-f file] [-c class] tag
  8.  * Options:    -t       output tag info, not the description
  9.  *        -f file       default filename for static functions
  10.  *        -c class   default class names for class functions
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include "config.h"
  15. extern char    *getenv();
  16. extern char    *fgets();
  17.  
  18.  
  19. /* This is the default path that is searched for tags */
  20. #if OSK
  21. # define DEFTAGPATH ".:/dd/defs:/dd/defs/sys:/dd/usr/src/lib:../lib:/dd/usr/lib"
  22. #else
  23. # if ANY_UNIX
  24. #  define DEFTAGPATH ".:/usr/include:/usr/include/sys:/usr/src/lib:../lib:/usr/local/lib"
  25. # else
  26. #  if MSDOS || TOS
  27. #   define DEFTAGPATH ".;C:\\include;C:\\include\\sys;C:\\lib;..\\lib"
  28. #   define SEP ';'
  29. #  else
  30. #   if AMIGA
  31. #    define DEFTAGPATH ".;Include:;Include:sys"
  32. #    define SEP ';'
  33. #   else /* any other OS */
  34. #    define DEFTAGPATH "."
  35. #   endif
  36. #  endif
  37. # endif
  38. #endif
  39.  
  40. #ifndef SEP
  41. # define SEP ':'
  42. #endif
  43.  
  44.  
  45. /* These variables reflect the command-line options given by the user. */
  46. int    taginfo;    /* boolean: give only the tag info? (not header?) */
  47. char    *def_file;    /* default filename for static functions */
  48. char    *def_class;    /* default classname for class members */
  49. int    colons;        /* #colons in tag: 0=normal, 1=static, 2=member */
  50.  
  51. /* This function checks for a tag in the "tags" file of given directory.
  52.  * If the tag is found, then it returns a pointer to a static buffer which
  53.  * contains the filename, a tab character, and a linespec for finding the
  54.  * the tag.  If the tag is not found in the "tags" file, or if the "tags"
  55.  * file cannot be opened or doesn't exist, then this function returns NULL.
  56.  */
  57. char *cktagdir(tag, dir)
  58.     char    *tag;    /* name of the tag to look for */
  59.     char    *dir;    /* name of the directory to check */
  60. {
  61.     char    buf[BLKSIZE];
  62.     static char found[BLKSIZE];
  63.     FILE    *tfile;
  64.     int    len;
  65.  
  66. #if AMIGA
  67.     if (dir[strlen(dir) - 1] == COLON)
  68.         sprintf(buf, "%s%s", dir, TAGS);   /* no slash after colon. */
  69.     else
  70. #endif
  71.     /* construct the name of the "tags" file in this directory */
  72.     sprintf(buf, "%s%c%s", dir, SLASH, TAGS);
  73.  
  74.     /* Try to open the tags file.  Return NULL if can't open */
  75. #if AMIGA
  76.     if (buf[0] == '.' && buf[1] == SLASH)
  77.         tfile = fopen(&buf[2], "r");
  78.     else
  79. #endif
  80.     tfile = fopen(buf, "r");
  81.     if (!tfile)
  82.     {
  83.         return (char *)0;
  84.     }
  85.  
  86.     /* compute the length of the tagname once */
  87.     len = strlen(tag);
  88.  
  89.     /* read lines until we get the one for this tag */
  90.     found[0] = '\0';
  91.     while (fgets(buf, sizeof buf, tfile))
  92.     {
  93.         /* is this the one we want? */
  94.         if (!strncmp(buf, tag, len) && buf[len] == '\t')
  95.         {
  96.             /* we've found a match -- remember it */
  97.             strcpy(found, buf);
  98.  
  99.             /* if there is no default file, or this match is in
  100.              * the default file, then we've definitely found the
  101.              * one we want.  Break out of the loop now.
  102.              */
  103.             if (!def_file || !strncmp(&buf[len + 1], def_file, strlen(def_file)))
  104.             {
  105.                 break;
  106.             }
  107.         }
  108.     }
  109.  
  110.     /* we're through reading */
  111.     fclose(tfile);
  112.  
  113.     /* if there's anything in found[], use it */
  114.     if (found[0])
  115.     {
  116.         return &found[len + 1];
  117.     }
  118.  
  119.     /* else we didn't find it */
  120.     return (char *)0;
  121. }
  122.  
  123. /* This function reads a single textline from a binary file.  It returns
  124.  * the number of bytes read, or 0 at EOF.
  125.  */
  126. int getline(buf, limit, fp)
  127.     char    *buf;    /* buffer to read into */
  128.     int    limit;    /* maximum characters to read */
  129.     FILE    *fp;    /* binary stream to read from */
  130. {
  131.     int    bytes;    /* number of bytes read so far */
  132.     int    ch;    /* single character from file */
  133.  
  134.     for (bytes = 0, ch = 0; ch != '\n' && --limit > 0 && (ch = getc(fp)) != EOF; bytes++)
  135.     {
  136. #if MSDOS || TOS
  137.         /* since this is a binary file, we'll need to manually strip CR's */
  138.         if (ch == '\r')
  139.         {
  140.             continue;
  141.         }
  142. #endif
  143.         *buf++ = ch;
  144.     }
  145.     *buf = '\0';
  146.  
  147.     return bytes;
  148. }
  149.  
  150.  
  151. /* This function reads a source file, looking for a given tag.  If it finds
  152.  * the tag, then it displays it and returns TRUE.  Otherwise it returns FALSE.
  153.  * To display the tag, it attempts to output any introductory comment, the
  154.  * tag line itself, and any arguments.  Arguments are assumed to immediately
  155.  * follow the tag line, and start with whitespace.  Comments are assumed to
  156.  * start with lines that begin with "/*", "//", "(*", or "--", and end at the
  157.  * tag line or at a blank line.
  158.  */
  159. int lookup(dir, entry)
  160.     char    *dir;    /* name of the directory that contains the source */
  161.     char    *entry;    /* source filename, <Tab>, linespec */
  162. {
  163.     char    buf[BLKSIZE];    /* pathname of sourcefile */
  164.     long    lnum;        /* line number */
  165.     long    here;        /* seek position where current line began */
  166.     long    comment;    /* seek position of introductory comment, or -1L */
  167.     FILE    *sfile;        /* used for reading the source file */
  168.     int    len;        /* length of string */
  169.     char    *ptr;
  170.  
  171.  
  172.     /* construct the pathname of the source file */
  173.     strcpy(buf, dir);
  174.     ptr = buf + strlen(buf);
  175. #if AMIGA
  176.     if (ptr[-1] != COLON)
  177. #endif
  178.     *ptr++ = SLASH;
  179.     while (*entry != '\t')
  180.     {
  181.         *ptr++ = *entry++;
  182.     }
  183.     *ptr = '\0';
  184.     entry++;
  185.  
  186.     /* searching for string or number? */
  187.     if (*entry >= '0' && *entry <= '9')
  188.     {
  189.         /* given a specific line number */
  190.         lnum = atol(entry);
  191.         entry = (char *)0;
  192.     }
  193.     else
  194.     {
  195.         /* given a string -- strip off "/^" and "$/\n" */
  196.         entry += 2;
  197.         len = strlen(entry) - 2;
  198.         if (entry[len - 1] == '$')
  199.         {
  200.             entry[len - 1] = '\n';
  201.         }
  202.         lnum = 0L;
  203.     }
  204.  
  205.     /* Open the file.  Note that we open the file in binary mode even
  206.      * though we know it is a text file, because ftell() and fseek()
  207.      * don't work on text files.
  208.      */
  209. #if MSDOS || TOS
  210.     sfile = fopen(buf, "rb");
  211. #else
  212. # if AMIGA
  213.     if (buf[0] == '.' && buf[1] == SLASH)
  214.         sfile = fopen(&buf[2], "r");
  215.     else
  216. # endif
  217.     sfile = fopen(buf, "r");
  218. #endif
  219.     if (!sfile)
  220.     {
  221.         /* can't open the real source file.  Try "refs" instead */
  222. #if AMIGA
  223.         if (dir[strlen(dir) - 1] == COLON)
  224.             sprintf(buf, "%srefs", dir);
  225.         else
  226. #endif
  227.         sprintf(buf, "%s%crefs", dir, SLASH);
  228. #if MSDOS || TOS
  229.         sfile = fopen(buf, "rb");
  230. #else
  231. # if AMIGA
  232.         if (buf[0] == '.' && buf[1] == SLASH)
  233.             sfile = fopen(&buf[2], "r");
  234.         else
  235. # endif
  236.         sfile = fopen(buf, "r");
  237. #endif
  238.         if (!sfile)
  239.         {
  240.             /* failed! */
  241.             return 0;
  242.         }
  243.     }
  244.  
  245.     /* search the file */
  246.     for (comment = -1L; here = ftell(sfile), getline(buf, BLKSIZE, sfile) > 0; )
  247.     {
  248.         /* Is this the start/end of a comment? */
  249.         if (comment == -1L)
  250.         {
  251.             /* starting a comment? */
  252.             if (buf[0] == '/' && buf[1] == '*'
  253.              || buf[0] == '/' && buf[1] == '/'
  254.              || buf[0] == '(' && buf[1] == '*'
  255.              || buf[0] == '-' && buf[1] == '-')
  256.             {
  257.                 comment = here;
  258.             }
  259.         }
  260.         else
  261.         {
  262.             /* ending a comment? */
  263.             if (buf[0] == '\n' || buf[0] == '#')
  264.             {
  265.                 comment = -1L;
  266.             }
  267.         }
  268.  
  269.         /* is this the tag line? */
  270.         if (--lnum == 0L || (entry && !strncmp(buf, entry, len)))
  271.         {
  272.             /* if there were introductory comments, show them */
  273.             if (comment != -1L)
  274.             {
  275.                 fseek(sfile, comment, 0);
  276.                 while (comment != here)
  277.                 {
  278.                     getline(buf, BLKSIZE, sfile);
  279.                     fputs(buf, stdout);
  280.                     comment = ftell(sfile);
  281.                 }
  282.  
  283.                 /* re-fetch the tag line */
  284.                 fgets(buf, BLKSIZE, sfile);
  285.             }
  286.  
  287.             /* show the tag line */
  288.             fputs(buf, stdout);
  289.  
  290.             /* show any argument lines */
  291.             while (getline(buf, BLKSIZE, sfile) > 0
  292.                 && buf[0] != '#'
  293.                 && strchr(buf, '{') == (char *)0)
  294.             {
  295.                 fputs(buf, stdout);
  296.             }
  297.  
  298.             /* Done!  Close the file, and return TRUE */
  299.             fclose(sfile);
  300.             return 1;
  301.         }
  302.     }
  303.  
  304.     /* not found -- return FALSE */
  305.     return 0;
  306. }
  307.  
  308. /* This function searches through the entire search path for a given tag.
  309.  * If it finds the tag, then it displays the info and returns TRUE;
  310.  * otherwise it returns FALSE.
  311.  */
  312. int find(tag)
  313.     char    *tag;    /* the tag to look up */
  314. {
  315.     char    *tagpath;
  316.     char    dir[80];
  317.     char    *ptr;
  318.     int    len;
  319.  
  320.     if (colons == 1)
  321.     {
  322.         /* looking for static function -- only look in current